using System;
using System.Collections.Generic;
using System.Text;

namespace Jeffrey.XFramework.XCrawl
{
    public class CrawlUri : Uri
    {
        public enum StatusCode
        {
            S_Succeed,

            E_UriNotFormatted,
            E_HostNotFound,
            E_ResolveHost,
            E_Connected,
            E_Sent,
            E_CannotDeterminePage,
            E_SetTimeOut,
            E_RequestSend,
            E_HeaderReceive,
            E_ResponsedCodeParse,
            E_ResponsedErrorCode,
            E_HeaderParse,
            E_ReceiveData,
            E_ReceiveChunkedData,
            E_PreFetch,
            E_Fetch,
            E_PostFetch,
            E_Extract,
            E_Filter,
            E_Storage,
            E_NeedRetry,
            E_RetryFailed,

            N_RejectedByAll,

            E_CustomizedError
        }

        public CrawlUri(String uriString)
            : base(uriString) { Initialize(); }

        public CrawlUri(Uri baseUri, Uri relativeUri)
            : base(baseUri, relativeUri) 
        {
            m_BaseUri = baseUri.AbsoluteUri;
            Initialize();
        }
        public CrawlUri(Uri baseUri, String relative)
            : base(baseUri, relative)
        {
            m_BaseUri = baseUri.AbsoluteUri;
            Initialize();
        }

        public void Initialize()
        {
            m_Status   = StatusCode.N_RejectedByAll;

            m_SocketError  = String.Empty;
            m_Content      = String.Empty;
            m_CustomizedError = String.Empty;
            m_Enc          = Encoding.Default;
            m_ResponseCode = 0;
            m_CanReTry     = true;
            
            m_NormalLinks   = new List<String>();
            m_PriorLinks = new List<String>();
        }

        public String Content
        {
            get { return m_Content; }
            set { m_Content = value; }
        }
        public Encoding ContentEncoding
        {
            get { return m_Enc; }
            set { m_Enc = value; }
        }
        public List<String> NormalLinks
        {
            get { return m_NormalLinks; }
        }
        public List<String> PriorLinks
        {
            get { return m_PriorLinks; }
        }
        public String BaseUri
        {
            get { return m_BaseUri; }
        }
        public StatusCode Status
        {
            get { return m_Status; }
            set 
            {
                if (value != StatusCode.E_CustomizedError)
                    throw new ArgumentException("Only can set status to E_CustomizedError!");
                else
                    m_Status = value;
            }
        }
        public String SocketError
        {
            get { return m_SocketError; }
        }
        public Int32 ResponseCode
        {
            get { return m_ResponseCode; }
        }
        public Int32 Depth
        {
            get { return m_Depth; }
        }
        public String CustomizedError
        {
            get { return m_CustomizedError; }
            set { m_CustomizedError = value; }
        }

        internal Int32    m_ResponseCode;
        internal Int32    m_Depth;
        internal String   m_Content;
        internal String   m_BaseUri;
        internal String   m_SocketError;
        internal String   m_CustomizedError;
        internal Encoding m_Enc;

        internal StatusCode m_Status;
        /*
         * indicate that if the current uri can processed again when error occurred...
         */
        internal Boolean m_CanReTry;

        internal List<String> m_NormalLinks;
        internal List<String> m_PriorLinks;
    }
}
